package com.cencat.merchant.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cencat.common.exception.BusinessException;
import com.cencat.common.response.ApiResponse;
import com.cencat.merchant.dto.MerchantCreateDTO;
import com.cencat.merchant.dto.MerchantQueryDTO;
import com.cencat.merchant.dto.MerchantUpdateDTO;
import com.cencat.merchant.entity.Merchant;
import com.cencat.merchant.service.MerchantService;
import com.cencat.merchant.service.MerchantAuditService;
import com.cencat.merchant.dto.MerchantAuditDTO;
import com.cencat.merchant.vo.MerchantAuditHistoryVO;
import com.cencat.merchant.vo.MerchantStatisticsVO;
import com.cencat.merchant.vo.MerchantVO;
import com.cencat.common.enums.AuditStatus;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商家管理控制器
 * @author cencat
 * @since 2024-01-01
 */
@RestController
@RequestMapping("/api/merchant")
@Tag(name = "商家管理", description = "商家管理相关接口")
@Slf4j
public class MerchantController {

    @Autowired
    private MerchantService merchantService;
    
    @Autowired
    private MerchantAuditService merchantAuditService;

    /**
     * 创建商家
     * @param merchant 商家信息
     * @return 商家ID
     */
    @PostMapping("/create")
    @Operation(summary = "创建商家", description = "创建新的商家信息")
    public ApiResponse<Long> createMerchant(@Valid @RequestBody Merchant merchant) {
        try {
            Long merchantId = merchantService.createMerchant(merchant);
            return ApiResponse.success(merchantId);
        } catch (BusinessException e) {
            log.error("创建商家失败: {}", e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("创建商家异常: {}", e.getMessage(), e);
            return ApiResponse.error("创建商家失败");
        }
    }

    /**
     * 更新商家信息
     * @param merchant 商家信息
     * @return 是否成功
     */
    @PutMapping("/update")
    @Operation(summary = "更新商家信息", description = "更新商家基本信息")
    public ApiResponse<Boolean> updateMerchant(@Valid @RequestBody Merchant merchant) {
        try {
            Boolean result = merchantService.updateMerchant(merchant);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商家信息失败: {}", e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("更新商家信息异常: {}", e.getMessage(), e);
            return ApiResponse.error("更新商家信息失败");
        }
    }

    /**
     * 删除商家
     * @param merchantId 商家ID
     * @return 是否成功
     */
    @DeleteMapping("/delete/{merchantId}")
    @Operation(summary = "删除商家", description = "删除指定商家")
    public ApiResponse<Boolean> deleteMerchant(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            Boolean result = merchantService.deleteMerchant(merchantId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("删除商家失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("删除商家异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("删除商家失败");
        }
    }

    /**
     * 根据ID获取商家信息
     * @param merchantId 商家ID
     * @return 商家信息
     */
    @GetMapping("/get/{merchantId}")
    @Operation(summary = "获取商家信息", description = "根据ID获取商家详细信息")
    public ApiResponse<Merchant> getMerchantById(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            Merchant merchant = merchantService.getMerchantById(merchantId);
            return ApiResponse.success(merchant);
        } catch (BusinessException e) {
            log.error("获取商家信息失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("获取商家信息异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("获取商家信息失败");
        }
    }

    /**
     * 根据商家编码获取商家信息
     * @param merchantCode 商家编码
     * @return 商家信息
     */
    @GetMapping("/getByCode/{merchantCode}")
    @Operation(summary = "根据编码获取商家信息", description = "根据商家编码获取商家详细信息")
    public ApiResponse<Merchant> getMerchantByCode(
            @Parameter(description = "商家编码", required = true)
            @PathVariable String merchantCode) {
        try {
            Merchant merchant = merchantService.getMerchantByCode(merchantCode);
            return ApiResponse.success(merchant);
        } catch (BusinessException e) {
            log.error("根据编码获取商家信息失败: merchantCode={}, error={}", merchantCode, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("根据编码获取商家信息异常: merchantCode={}, error={}", merchantCode, e.getMessage(), e);
            return ApiResponse.error("获取商家信息失败");
        }
    }

    /**
     * 根据租户ID获取商家列表
     * @param tenantId 租户ID
     * @return 商家列表
     */
    @GetMapping("/listByTenant/{tenantId}")
    @Operation(summary = "获取租户商家列表", description = "根据租户ID获取商家列表")
    public ApiResponse<List<Merchant>> getMerchantsByTenantId(
            @Parameter(description = "租户ID", required = true)
            @PathVariable @NotNull @Min(1) Long tenantId) {
        try {
            List<Merchant> merchants = merchantService.getMerchantsByTenantId(tenantId);
            return ApiResponse.success(merchants);
        } catch (BusinessException e) {
            log.error("获取租户商家列表失败: tenantId={}, error={}", tenantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("获取租户商家列表异常: tenantId={}, error={}", tenantId, e.getMessage(), e);
            return ApiResponse.error("获取商家列表失败");
        }
    }

    /**
     * 分页查询商家列表
     * @param current 当前页
     * @param size 页大小
     * @param tenantId 租户ID
     * @param merchantName 商家名称
     * @param status 状态
     * @param merchantLevel 商家等级
     * @return 分页结果
     */
    @GetMapping("/page")
    @Operation(summary = "分页查询商家", description = "分页查询商家列表")
    public ApiResponse<IPage<Merchant>> getMerchantsPage(
            @Parameter(description = "当前页", required = true)
            @RequestParam @Min(1) int current,
            @Parameter(description = "页大小", required = true)
            @RequestParam @Min(1) int size,
            @Parameter(description = "租户ID")
            @RequestParam(required = false) Long tenantId,
            @Parameter(description = "商家名称")
            @RequestParam(required = false) String merchantName,
            @Parameter(description = "状态")
            @RequestParam(required = false) Integer status,
            @Parameter(description = "商家等级")
            @RequestParam(required = false) Integer merchantLevel) {
        try {
            com.baomidou.mybatisplus.extension.plugins.pagination.Page<Merchant> pageParam = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, size);
            IPage<Merchant> page = merchantService.getMerchantPage(pageParam, tenantId, merchantName, 
                    status != null ? status.toString() : null, 
                    merchantLevel != null ? merchantLevel.toString() : null, 
                    null);
            return ApiResponse.success(page);
        } catch (BusinessException e) {
            log.error("分页查询商家失败: error={}", e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("分页查询商家异常: error={}", e.getMessage(), e);
            return ApiResponse.error("查询商家列表失败");
        }
    }

    /**
     * 提交商家审核
     * @param merchantId 商家ID
     * @param auditDTO 审核信息
     * @return 是否成功
     */
    @PostMapping("/audit/submit/{merchantId}")
    @Operation(summary = "提交商家审核", description = "提交商家审核申请")
    public ApiResponse<Boolean> submitAudit(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId,
            @Parameter(description = "审核信息")
            @RequestBody @Valid MerchantAuditDTO auditDTO) {
        try {
            Boolean result = merchantAuditService.submitAudit(merchantId, auditDTO);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("提交商家审核失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("提交商家审核异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("提交审核失败");
        }
    }

    /**
     * 审核商家
     * @param merchantId 商家ID
     * @param auditStatus 审核状态
     * @param auditRemark 审核备注
     * @return 是否成功
     */
    @PutMapping("/audit/{merchantId}")
    @Operation(summary = "审核商家", description = "审核商家申请")
    public ApiResponse<Boolean> auditMerchant(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId,
            @Parameter(description = "审核状态", required = true)
            @RequestParam @NotNull String auditStatus,
            @Parameter(description = "审核备注")
            @RequestParam(required = false) String auditRemark) {
        try {
            // 获取当前用户ID，这里暂时使用1L作为默认值
            Long auditorId = 1L; // TODO: 从当前登录用户获取
            AuditStatus status = AuditStatus.valueOf(auditStatus);
            Boolean result = merchantAuditService.auditMerchant(merchantId, status, auditRemark, auditorId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("审核商家失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("审核商家异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("审核商家失败");
        }
    }

    /**
     * 批量审核商家
     * @param merchantIds 商家ID列表
     * @param auditStatus 审核状态
     * @param auditRemark 审核备注
     * @return 是否成功
     */
    @PutMapping("/audit/batch")
    @Operation(summary = "批量审核商家", description = "批量审核商家申请")
    public ApiResponse<Boolean> batchAuditMerchants(
            @Parameter(description = "商家ID列表", required = true)
            @RequestParam @NotNull List<Long> merchantIds,
            @Parameter(description = "审核状态", required = true)
            @RequestParam @NotNull String auditStatus,
            @Parameter(description = "审核备注")
            @RequestParam(required = false) String auditRemark) {
        try {
            // 获取当前用户ID，这里暂时使用1L作为默认值
            Long auditorId = 1L; // TODO: 从当前登录用户获取
            AuditStatus status = AuditStatus.valueOf(auditStatus);
            Boolean result = merchantAuditService.batchAuditMerchants(merchantIds, status, auditRemark, auditorId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("批量审核商家失败: merchantIds={}, error={}", merchantIds, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("批量审核商家异常: merchantIds={}, error={}", merchantIds, e.getMessage(), e);
            return ApiResponse.error("批量审核失败");
        }
    }

    /**
     * 撤回审核
     * @param merchantId 商家ID
     * @param reason 撤回原因
     * @return 是否成功
     */
    @PutMapping("/audit/withdraw/{merchantId}")
    @Operation(summary = "撤回审核", description = "撤回商家审核申请")
    public ApiResponse<Boolean> withdrawAudit(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId,
            @Parameter(description = "撤回原因")
            @RequestParam(required = false) String reason) {
        try {
            Boolean result = merchantAuditService.withdrawAudit(merchantId, reason);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("撤回审核失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("撤回审核异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("撤回审核失败");
        }
    }

    /**
     * 获取审核历史
     * @param merchantId 商家ID
     * @return 审核历史列表
     */
    @GetMapping("/audit/history/{merchantId}")
    @Operation(summary = "获取审核历史", description = "获取商家审核历史记录")
    public ApiResponse<List<MerchantAuditHistoryVO>> getAuditHistory(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            List<MerchantAuditHistoryVO> result = merchantAuditService.getAuditHistory(merchantId);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取审核历史异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("获取审核历史失败");
        }
    }

    /**
     * 获取待审核商家列表
     * @param tenantId 租户ID
     * @return 待审核商家ID列表
     */
    @GetMapping("/audit/pending")
    @Operation(summary = "获取待审核商家列表", description = "获取待审核的商家ID列表")
    public ApiResponse<List<Long>> getPendingAuditMerchants(
            @Parameter(description = "租户ID")
            @RequestParam(required = false) Long tenantId) {
        try {
            // 获取当前用户ID，这里暂时使用1L作为默认值
            Long auditorId = 1L; // TODO: 从当前登录用户获取
            List<Long> result = merchantAuditService.getPendingAuditMerchants(tenantId, auditorId);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取待审核商家列表异常: tenantId={}, error={}", tenantId, e.getMessage(), e);
            return ApiResponse.error("获取待审核列表失败");
        }
    }

    /**
     * 自动审核
     * @param merchantId 商家ID
     * @return 是否成功
     */
    @PostMapping("/audit/auto/{merchantId}")
    @Operation(summary = "自动审核", description = "系统自动审核商家")
    public ApiResponse<Boolean> autoAudit(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            Boolean result = merchantAuditService.autoAudit(merchantId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("自动审核失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("自动审核异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("自动审核失败");
        }
    }

    /**
     * 获取审核统计信息
     * @param tenantId 租户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 审核统计信息
     */
    @GetMapping("/audit/statistics")
    @Operation(summary = "获取审核统计信息", description = "获取商家审核统计数据")
    public ApiResponse<Object> getAuditStatistics(
            @Parameter(description = "租户ID")
            @RequestParam(required = false) Long tenantId,
            @Parameter(description = "开始日期")
            @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期")
            @RequestParam(required = false) String endDate) {
        try {
            Object result = merchantAuditService.getAuditStatistics(tenantId, startDate, endDate);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取审核统计信息异常: tenantId={}, error={}", tenantId, e.getMessage(), e);
            return ApiResponse.error("获取统计信息失败");
        }
    }

    /**
     * 启用商家
     * @param merchantId 商家ID
     * @return 是否成功
     */
    @PutMapping("/enable/{merchantId}")
    @Operation(summary = "启用商家", description = "启用指定商家")
    public ApiResponse<Boolean> enableMerchant(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            Boolean result = merchantService.enableMerchant(merchantId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("启用商家失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("启用商家异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("启用商家失败");
        }
    }

    /**
     * 禁用商家
     * @param merchantId 商家ID
     * @return 是否成功
     */
    @PutMapping("/disable/{merchantId}")
    @Operation(summary = "禁用商家", description = "禁用指定商家")
    public ApiResponse<Boolean> disableMerchant(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId) {
        try {
            Boolean result = merchantService.disableMerchant(merchantId);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("禁用商家失败: merchantId={}, error={}", merchantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("禁用商家异常: merchantId={}, error={}", merchantId, e.getMessage(), e);
            return ApiResponse.error("禁用商家失败");
        }
    }

    /**
     * 更新商家等级
     * @param merchantId 商家ID
     * @param level 商家等级
     * @return 是否成功
     */
    @PutMapping("/updateLevel/{merchantId}")
    @Operation(summary = "更新商家等级", description = "更新商家等级")
    public ApiResponse<Boolean> updateMerchantLevel(
            @Parameter(description = "商家ID", required = true)
            @PathVariable @NotNull @Min(1) Long merchantId,
            @Parameter(description = "商家等级", required = true)
            @RequestParam @NotNull Integer level) {
        try {
            Boolean result = merchantService.updateMerchantLevel(merchantId, level);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商家等级失败: merchantId={}, level={}, error={}", merchantId, level, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("更新商家等级异常: merchantId={}, level={}, error={}", merchantId, level, e.getMessage(), e);
            return ApiResponse.error("更新商家等级失败");
        }
    }

    /**
     * 生成商家编码
     * @return 商家编码
     */
    @GetMapping("/generateCode")
    @Operation(summary = "生成商家编码", description = "生成唯一的商家编码")
    public ApiResponse<String> generateMerchantCode() {
        try {
            // 获取当前租户ID，这里暂时使用1L作为默认值
            Long tenantId = 1L; // TODO: 从当前登录用户获取租户ID
            String merchantCode = merchantService.generateMerchantCode(tenantId);
            return ApiResponse.success(merchantCode);
        } catch (BusinessException e) {
            log.error("生成商家编码失败: error={}", e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("生成商家编码异常: error={}", e.getMessage(), e);
            return ApiResponse.error("生成商家编码失败");
        }
    }

    /**
     * 获取商家统计信息
     * @param tenantId 租户ID
     * @return 统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取商家统计", description = "获取商家统计信息")
    public ApiResponse<Map<String, Object>> getMerchantStatistics(
            @Parameter(description = "租户ID")
            @RequestParam(required = false) Long tenantId) {
        try {
            // 获取商家统计信息
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("totalCount", merchantService.countMerchantsByTenantId(tenantId));
            statistics.put("statusCount", merchantService.countMerchantsByStatus(tenantId));
            return ApiResponse.success(statistics);
        } catch (BusinessException e) {
            log.error("获取商家统计失败: tenantId={}, error={}", tenantId, e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("获取商家统计异常: tenantId={}, error={}", tenantId, e.getMessage(), e);
            return ApiResponse.error("获取统计信息失败");
        }
    }



    /**
     * 导出商家数据
     * @param tenantId 租户ID
     * @param merchantIds 商家ID列表
     * @return 导出结果
     */
    @GetMapping("/export")
    @Operation(summary = "导出商家数据", description = "导出商家数据到Excel文件")
    public ResponseEntity<byte[]> exportMerchants(
            @Parameter(description = "租户ID") @RequestParam Long tenantId,
            @Parameter(description = "商家ID列表") @RequestParam(required = false) List<Long> merchantIds) {
        try {
            byte[] data = merchantService.exportMerchants(tenantId, merchantIds);
            return ResponseEntity.ok()
                    .header("Content-Disposition", "attachment; filename=merchants.xlsx")
                    .body(data);
        } catch (Exception e) {
            log.error("导出商家数据失败: {}", e.getMessage());
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 导入商家数据
     * @param file Excel文件
     * @return 导入结果
     */
    @PostMapping("/import")
    @Operation(summary = "导入商家数据", description = "从Excel文件导入商家数据")
    public ApiResponse<Map<String, Object>> importMerchants(
            @Parameter(description = "Excel文件", required = true)
            @RequestParam("file") MultipartFile file) {
        try {
            Map<String, Object> result = merchantService.importMerchants(file);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("导入商家数据失败: fileName={}, error={}", file.getOriginalFilename(), e.getMessage());
            return ApiResponse.error(e.getErrorCode());
        } catch (Exception e) {
            log.error("导入商家数据异常: fileName={}, error={}", file.getOriginalFilename(), e.getMessage(), e);
            return ApiResponse.error("导入数据失败");
        }
    }
}